#include<iostream>
#include <sys/types.h>
#include <unistd.h>
#include "queueblock.hpp"
#include "task.hpp"

using namespace std;


#define key_type Task

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

void *consumer(void *argv)
{
    queue_block<key_type> *qb = static_cast<queue_block<key_type> *>(argv);

    while (true)
    {
        //sleep(1);
        Task out ;
        qb->pop(&out);
        out();
        pthread_mutex_lock(&mutex);
        //cout << "consumer :"<<"pop()"<< endl;
        out.display_result();
        pthread_mutex_unlock(&mutex);

    }
}

void *productor(void *argv)
{
    queue_block<key_type> *qb = static_cast<queue_block<key_type> *>(argv);
    string opers = "+-*/%";
    while (true)
    {
        sleep(1);
        //int in = rand()%10 +1 ;
        int x = rand()%20 +1 ;
        int y = rand()%10 +1 ;
        char op = opers[rand()%5] ;


        Task in(x,y,op);
        qb->push(in);


        // Task *in = new Task(x,y,op);
        // qb->push(*in);

        pthread_mutex_lock(&mutex);
        //cout << "productor :"<<"push()"<< endl;
        //cout << x<<op<<y<<"="<<"?"<< endl;
        in.display_question();
        pthread_mutex_unlock(&mutex);

    }

}

int main()
{
    srand((unsigned int)time(nullptr) ^ getpid());
    queue_block<key_type> *qb = new queue_block<key_type>();

    pthread_t c[2],p[2];
    pthread_create(c,nullptr,consumer,qb);
    //pthread_create(c+1,nullptr,consumer,qb);
    //pthread_create(c+2,nullptr,consumer,qb);

    //pthread_create(p,nullptr,productor,qb);
    //pthread_create(p+1,nullptr,productor,qb);
    pthread_create(p+2,nullptr,productor,qb);


    pthread_join(c[0],nullptr);
    //pthread_join(c[1],nullptr);
    //pthread_join(c[2],nullptr);

    pthread_join(p[0],nullptr);
    //(p[1],nullptr);
    //pthread_join(p[2],nullptr);




    delete qb;


    return 0;
}



//*************************************************
//*************************************************
//int版本

// #define key_type int

// pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

// void *consumer(void *argv)
// {
//     queue_block<key_type> *qb = static_cast<queue_block<key_type> *>(argv);

//     while (true)
//     {
//         sleep(1);
//         int out = 0 ;
//         qb->pop(&out);
//         pthread_mutex_lock(&mutex);
//         cout << "consumer :"<<"pop("<<out<<")" << endl;
//         pthread_mutex_unlock(&mutex);

//     }
// }

// void *productor(void *argv)
// {
//     queue_block<key_type> *qb = static_cast<queue_block<key_type> *>(argv);
//     while (true)
//     {
//         //sleep(1);
//         int in = rand()%10 +1 ;
//         qb->push(in);

//         pthread_mutex_lock(&mutex);
//         cout << "productor :"<<"push("<<in<<")"<< endl;
//         pthread_mutex_unlock(&mutex);

//     }

// }

// int main()
// {
//     srand((unsigned int)time(nullptr) ^ getpid());
//     queue_block<key_type> *qb = new queue_block<key_type>();

//     pthread_t c[2],p[2];
//     pthread_create(c,nullptr,consumer,qb);
//     pthread_create(c+1,nullptr,consumer,qb);
//     pthread_create(c+2,nullptr,consumer,qb);

//     pthread_create(p,nullptr,productor,qb);
//     pthread_create(p+1,nullptr,productor,qb);
//     pthread_create(p+2,nullptr,productor,qb);


//     pthread_join(c[0],nullptr);
//     pthread_join(c[1],nullptr);
//     pthread_join(c[2],nullptr);

//     pthread_join(p[0],nullptr);
//     pthread_join(p[1],nullptr);
//     pthread_join(p[2],nullptr);




//     delete qb;


//     return 0;
// }